﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using PostSharp.Laos;
using System.ComponentModel;
using System.Reflection;

namespace DemoMidiDuSkill.Tools.Aspect
{
    /// <summary>
    /// Calls the specified method when a property has been changed
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
    public class NotifyPropertyChangedAttribute : OnMethodBoundaryAspect
    {
        private const String Set_Method_Prefix = "set_";

        #region Initialization

        /// <summary>
        /// Default constructor
        /// </summary>
        public NotifyPropertyChangedAttribute(String pMethodName)
        {
            MethodName = pMethodName;
        }

        #endregion

        #region Public properties

        /// <summary>
        /// Name of the method to call at property changed event
        /// </summary>
        public String MethodName { get; set; }

        #endregion

        #region Custom OnMethodBoundaryAspect methods

        public override void OnSuccess(MethodExecutionEventArgs eventArgs)
        {
            PropertyInfo vPropertyInfo = null;
            if (eventArgs.Instance is INotifyPropertyChanged
                && eventArgs.Method.Name.StartsWith(Set_Method_Prefix)
                && (vPropertyInfo = eventArgs.Instance.GetType().GetProperty(eventArgs.Method.Name.Substring(Set_Method_Prefix.Length))) != null)
            {
                MethodInfo vMethodInfo = null;
                if ((vMethodInfo = eventArgs.Instance.GetType().GetMethod(MethodName)) != null)
                    vMethodInfo.Invoke(eventArgs.Instance, new object[] { vPropertyInfo.Name });
                else
                    throw new Exception(String.Format("Unable to find the method {0} in class {1}.", MethodName, eventArgs.Instance.GetType().Name));
            }
            base.OnSuccess(eventArgs);
        }

        #endregion
    }
}
